﻿using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;

using Outcoder;
using Outcoder.Linq;
using Outcoder.Services;
using Outcoder.UI.Xaml;
using Outcoder.UserOptionsModel;

namespace CalciumTemplateApp.Views
{
	/// <summary>
	/// Allows the user to change options 
	/// that affect the behavior of the app.
	/// </summary>
    public class OptionsViewModel : ViewModel
    {
	    IUserOptionsService userOptionsService;

	    public OptionsViewModel(IUserOptionsService userOptionsService) 
			: base(() => AppResources.Views_Options_Title)
	    {
		    this.userOptionsService = ArgumentValidator.AssertNotNull(
										userOptionsService, "userOptionsService");

		    LoadOptions();

			exampleCommand = new UICommand("Test", ExecuteExampleCommand) { Text = "Button 1" };
	    }

		public async Task Load()
		{
			await LoadOptions();
		}

		public async Task Unload()
		{
			await UnloadOptions();
		}

	    async Task LoadOptions()
	    {
			IUserOptionGroupings tempGroupings = userOptionsService.UserOptionGroupings;
			Groupings = tempGroupings;
	    }

		IUserOptionGroupings groupings;

		public IUserOptionGroupings Groupings
		{
			get
			{
				return groupings;
			}
			private set
			{
				Assign(ref groupings, value);
			}
		}

		async Task UnloadOptions()
		{
			SaveOptions();
		}

		/// <summary>
		/// This method may be called to explicitly save the options.
		/// Though, by default an option is saved as soon as it is changed.
		/// </summary>
		void SaveOptions()
		{
			if (groupings == null)
			{
				return;
			}

			foreach (IGrouping<IOptionCategory, IUserOptionReaderWriter> grouping
														in groupings)
			{
				foreach (IUserOptionReaderWriter writer in grouping)
				{
					writer.Save();
				}
			}
		}

		readonly UICommand exampleCommand;

		public ICommand ExampleCommand
		{
			get
			{
				return exampleCommand;
			}
		}

		async Task ExecuteExampleCommand(object arg)
		{
			await DialogService.ShowMessageAsync("Example command");
		}
    }
}
